package com.coolingme.lazy02;

/**
 * 懒汉式静态内部类单例模式
 * <p>
 * 这种形式兼顾饿汉式的内存浪费，也兼顾 synchronized 性能问题。
 * 内部类一定是要在方 法调用之前初始化，巧妙地避免了线程安全问题
 *
 * @author wangyue
 * @date 2020/9/29 10:14
 */
public class LazyInnerClassSingleton {

    /**
     * 当前构造函数会被反射破坏
     */
//    private LazyInnerClassSingleton() {
//    }

    /**
     * 当使用反射获取实例对象时，会抛出异常，
     *
     * <p>
     * 默认使用LazyInnerClassSingleton时，会先初始化内部类
     * 如果没有使用的话，内部类是不会加载的
     */
    private LazyInnerClassSingleton() {
        // 当反射constructor.newInstance() 时，执行InnerClass.singleton时，静态内部类已经初始化了
        System.out.println("懒汉式静态内部类实例对象：" + InnerClass.singleton);
        if (InnerClass.singleton != null) {
            throw new RuntimeException("LazyInnerClassSingleton禁止创建多个实例");
        }
    }

    /**
     * 对外提供实例的接口
     * static 使单例的空间共享
     * final 保证这个方法不被重载覆盖
     *
     * @return LazyInnerClassSingleton
     */
    public static final LazyInnerClassSingleton getInstance() {
        return InnerClass.singleton;
    }

    /**
     * 静态内部类,默认不加载
     */
    private static final class InnerClass {
        private static final LazyInnerClassSingleton singleton = new LazyInnerClassSingleton();

        static {
            System.out.println("初始化实例对象:" + singleton);
        }
    }


    public static void main(String[] args) {
        LazyInnerClassSingleton instance1 = LazyInnerClassSingleton.getInstance();
        LazyInnerClassSingleton instance2 = LazyInnerClassSingleton.getInstance();
        System.out.println(instance1);
        System.out.println(instance2);
        System.out.println(instance1 == instance2);
    }


}
